/*
@(#)WorkUserServiceImpl   2023-04-17
 
Copyright (c) 2011-2023 杭州湖畔网络技术有限公司 
保留所有权利 
本软件为杭州湖畔网络技术有限公司所有及包含机密信息，须遵守其相关许可证条款进行使用。
Copyright (c) 2011-2023 HUPUN Network Technology CO.,LTD.
All rights reserved.
This software is the confidential and proprietary information of HUPUN
Network Technology CO.,LTD("Confidential Information").  You shall not
disclose such Confidential Information and shall use it only in
accordance with the terms of the license agreement you entered into with HUPUN.
Website：http://www.hupun.com
*/
package org.obp.upms.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.obp.auth.consts.SendSmsTypeEnum;
import org.obp.auth.exception.AuthExceptionEnum;
import org.obp.auth.redis.RedisLoginHelper;
import org.obp.auth.utils.MobileUtils;
import org.obp.core.exception.BizException;
import org.obp.upms.domain.request.LoginPasswdParam;
import org.obp.upms.domain.request.ResetPasswdParam;
import org.obp.upms.mapper.WorkUserDAO;
import org.obp.upms.model.WorkRoleDO;
import org.obp.upms.model.WorkUserDO;
import org.obp.upms.model.WorkUserRoleDO;
import org.obp.upms.service.WorkUserRoleService;
import org.obp.upms.service.WorkUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author: Jackey 2023/4/17
 */
@Service
public class WorkUserServiceImpl extends ServiceImpl<WorkUserDAO, WorkUserDO> implements WorkUserService {

    @Autowired
    private WorkUserRoleService workUserRoleService;
    @Autowired
    private RedisLoginHelper redisLoginHelper;

    @Override
    public WorkUserDO login(LoginPasswdParam loginPasswdParam) {
        WorkUserDO workUserDO = this.lambdaQuery()
                .eq(WorkUserDO::getNation, loginPasswdParam.getNation())
                .eq(WorkUserDO::getMobile, loginPasswdParam.getMobile()).one();
        if (workUserDO == null ||
                !SaSecureUtil.aesEncrypt(WorkUserDO.AES_KEY, loginPasswdParam.getPassword()).equals(workUserDO.getPassword())) {
            throw new BizException(AuthExceptionEnum.ACCOUNT_OR_PASSWD_ERROR);
        }
        if (workUserDO.getUserStatus().equals(WorkUserDO.UserStatusEnum.DISABLE.status)) {
            throw new BizException(AuthExceptionEnum.ACCOUNT_IS_FROZEN);
        }
        return workUserDO;
    }

    @Override
    @Transactional
    public WorkUserDO insert(WorkUserDO workUserDO, List<WorkRoleDO> userRoles) {
        workUserDO.setPassword(SaSecureUtil.aesEncrypt(WorkUserDO.AES_KEY, workUserDO.getPassword()));
        this.save(workUserDO);
        for (WorkRoleDO workRoleDO : userRoles) {
            WorkUserRoleDO workUserRoleDO = new WorkUserRoleDO();
            workUserRoleDO.setUserId(workUserDO.getId());
            workUserRoleDO.setRoleId(workRoleDO.getId());
            workUserRoleService.saveOrUpdate(workUserRoleDO, new QueryWrapper<WorkUserRoleDO>().lambda()
                    .eq(WorkUserRoleDO::getUserId, workUserDO.getId())
                    .eq(WorkUserRoleDO::getRoleId, workRoleDO.getId()));
        }
        return workUserDO;
    }

    @Override
    @Transactional
    public boolean update(WorkUserDO workUserDO, List<WorkRoleDO> userRoles) {
        this.updateById(workUserDO);
        workUserRoleService.remove(new QueryWrapper<WorkUserRoleDO>().lambda()
                .eq(WorkUserRoleDO::getUserId, workUserDO.getId()));
        for (WorkRoleDO workRoleDO : userRoles) {
            WorkUserRoleDO workUserRoleDO = new WorkUserRoleDO();
            workUserRoleDO.setUserId(workUserDO.getId());
            workUserRoleDO.setRoleId(workRoleDO.getId());
            workUserRoleService.save(workUserRoleDO);
        }
        return true;
    }

    @Override
    public boolean resetPassword(ResetPasswdParam resetPasswdParam) {

        String nation = resetPasswdParam.getNation().trim();
        String mobile = resetPasswdParam.getMobile().trim();
        String code = resetPasswdParam.getCode().trim();

        if (!MobileUtils.checkMobile(nation.replaceAll("\\+", ""), mobile)) {
            throw new BizException(AuthExceptionEnum.MOBILE_INCORRECT);
        }

        String type = String.valueOf(SendSmsTypeEnum.RESET_PASSWD.type);
        this.verifySmsCode(nation, mobile, code, type);

        String password = SaSecureUtil.aesEncrypt(WorkUserDO.AES_KEY, resetPasswdParam.getPassword());
        return this.lambdaUpdate().set(WorkUserDO::getPassword, password)
                .eq(WorkUserDO::getNation, resetPasswdParam.getNation())
                .eq(WorkUserDO::getMobile, resetPasswdParam.getMobile()).update();
    }

    private void verifySmsCode(String nation, String mobile, String code, String type) {
        if (!redisLoginHelper.checkSmsCodeErrorCount(nation, mobile, type)) {
            throw new BizException(AuthExceptionEnum.CODE_ERROR_LIMIT);
        }
        String smsCode = redisLoginHelper.getSmsCode(nation, mobile, type);
        if (smsCode == null) {
            throw new BizException(AuthExceptionEnum.CODE_IS_ERROR);
        }
        if (!code.equals(smsCode)) {
            redisLoginHelper.incrSmsCodeErrorCount(nation, mobile, type);
            throw new BizException(AuthExceptionEnum.CODE_IS_ERROR);
        }
        this.clearSmsLimit(nation, mobile, type);
    }

    private void clearSmsLimit(String nation, String mobile, String type) {
        redisLoginHelper.delSmsCode(nation, mobile, type);
        redisLoginHelper.delSmsCodeErrorCount(nation, mobile, type);
        redisLoginHelper.delSmsInterval(nation, mobile);
    }

}